#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <cassert>
#include <functional>
#include <pthread.h>

using namespace std;

class Thread;

// 上下文,当成一个大号的结构体
class Context
{
    public:
        Thread *this_;
        void *args_;
    public:
        Context():this_(nullptr),args_(nullptr)
        { }
        ~Context()
        { }
};

class Thread
{
    public:
        // using func_t = function<void*(void*)>;
        typedef function<void*(void*)> func_t;
        const int num = 1024;
    public:
        Thread(func_t func, void *args = nullptr, int number = 0):func_(func), args_(args)
        {
            // name_ = "thread-";
            // name_ += to_string(number);

            char buffer[num];
            snprintf(buffer, sizeof buffer, "thread-%d", number);
            name_ = buffer;

            Context *ctx = new Context();
            ctx->this_ = this;
            ctx->args_ = args_;
            int n = pthread_create(&tid_, nullptr, start_routine, ctx);
            assert(n == 0);// 编译debug的方式存在,release方式发布就不存在,assert不存在,n就是定义了但未使用的变量,有些编译器会warning
            (void)n;
        }

        // 在类内创建线程,想让线程执行对应的方法,需要将方法设置成为static
        static void *start_routine(void *args)
        {
            Context *ctx = static_cast<Context *>(args);
            void *ret = ctx->this_->run(ctx->args_);
            delete ctx;
            return ret;
            // 静态方法不能调用成员方法或者成员变量
        }

        void join()
        {
            int n = pthread_join(tid_, nullptr);
            assert(n == 0);
            (void)n;
        }

        void *run(void *args)
        {
            return func_(args);
        }

        ~Thread()
        { }
    private:
        string name_;
        pthread_t tid_;
        func_t func_;
        void *args_;
};